use pest_meta::{optimizer, parser, validator};
use pest_meta::parser::Rule;
use pest_vm::Vm;

use std::fs;
use std::path::Path;
use pest_fmt::Formatter;
use pest::iterators::Pair;

/// 格式化语法代码
#[tauri::command]
fn format_grammar(grammar: &str) -> Result<String, String> {
    if grammar.is_empty() {
        return Ok(String::new());
    }
    let formatter = Formatter::new(grammar);
    match formatter.format() {
        Ok(formatted) => Ok(formatted),
        Err(_e) => Err(grammar.to_string())
    }
}

/// 虚拟机运行规则
#[tauri::command]
fn run_grammar(grammar_text: &str, rule_name: &str, input_text: &str) -> Result<String, String> {
    // 1. 编译 grammar
    let pairs = parser::parse(Rule::grammar_rules, grammar_text)
        .map_err(|e| format!("Grammar parse error: {}", e))?;

    // 2. 验证
    validator::validate_pairs(pairs.clone())
        .map_err(|errors| format!("Validation error: {:?}", errors))?;

    // 3. 生成 AST
    let ast = parser::consume_rules(pairs)
        .map_err(|errors| format!("AST error: {:?}", errors))?;

    // 4. 检查规则是否存在
    let rule_exists = ast.iter().any(|rule| rule.name == rule_name);
    if !rule_exists {
        // let available_rules: Vec<&str> = ast.iter().map(|rule| rule.name.as_str()).collect();
        return Err(format!("不存在此规则：'{}'", rule_name));
    }

    // 4. 创建虚拟机
    let vm = Vm::new(optimizer::optimize(ast));

    // 5. 解析输入
    match vm.parse(rule_name, input_text) {
        Ok(pairs) => {
            // 使用 format_pair 格式化所有匹配结果
            let lines: Vec<String> = pairs
                .map(|pair| format_pair(pair, 0, true))
                .collect();
            Ok(lines.join("\n"))
        }
        Err(e) => Err(format!("Parse error: {}", e))
    }
}

/// 格式化AST
fn format_pair(pair: Pair<&str>, indent_level: usize, is_newline: bool) -> String {
    let indent = if is_newline {
        "  ".repeat(indent_level)
    } else {
        String::new()
    };

    let children: Vec<_> = pair.clone().into_inner().collect();
    let len = children.len();
    let children: Vec<_> = children
        .into_iter()
        .map(|pair| {
            format_pair(
                pair,
                if len > 1 {
                    indent_level + 1
                } else {
                    indent_level
                },
                len > 1,
            )
        })
        .collect();

    let dash = if is_newline { "- " } else { "" };
    let pair_tag = match pair.as_node_tag() {
        Some(tag) => format!("(#{}) ", tag),
        None => String::new(),
    };
    match len {
        0 => format!(
            "{}{}{}{}: {:?}",
            indent,
            dash,
            pair_tag,
            pair.as_rule(),
            pair.as_span().as_str()
        ),
        1 => format!(
            "{}{}{}{} > {}",
            indent,
            dash,
            pair_tag,
            pair.as_rule(),
            children[0]
        ),
        _ => format!(
            "{}{}{}{}\n{}",
            indent,
            dash,
            pair_tag,
            pair.as_rule(),
            children.join("\n")
        ),
    }
}

/// 获取所有规则
#[tauri::command]
fn get_all_rules(grammar_text: &str) -> Result<Vec<String>, String> {
    // 1. 解析 grammar
    let pairs = parser::parse(Rule::grammar_rules, grammar_text)
        .map_err(|e| format!("Parse error: {}", e))?;

    // 2. 验证规则
    validator::validate_pairs(pairs.clone())
        .map_err(|errors| format!("Validation errors: {:?}", errors))?;

    // 3. 生成 AST
    let ast = parser::consume_rules(pairs)
        .map_err(|errors| format!("AST errors: {:?}", errors))?;

    // 4. 遍历所有规则并收集名称
    let rule_names: Vec<String> = ast.iter()
        .map(|rule| {
            // println!("Rule name: {}", rule.name);
            // println!("Rule ty: {:?}", rule.ty); // 规则类型 (Normal, Silent, Atomic, etc.)
            // println!("Rule node tag: {:?}", rule.expr); // 节点标签
            rule.name.clone()
        })
        .collect();

    Ok(rule_names)
}

/// 读取文件内容
#[tauri::command]
fn get_file_content(file_path: &str) -> Result<String, String> {

    // 安全检查：确保路径在应用允许的范围内
    let path = Path::new(file_path);

    // 检查文件是否存在
    if !path.exists() {
        return Err("文件不存在".to_string());
    }

    // 检查是否为文件
    if !path.is_file() {
        return Err("指定路径不是文件".to_string());
    }

    // 读取文件内容
    match fs::read_to_string(path) {
        Ok(content) => Ok(content),
        Err(e) => Err(format!("读取文件失败: {}", e)),
    }
}

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_opener::init())
        .plugin(tauri_plugin_dialog::init())
        .invoke_handler(tauri::generate_handler![
            run_grammar,
            get_all_rules,
            get_file_content,
            format_grammar
        ])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}
